import { IVec2 } from "../../util/Defined";
import { TypeUtil } from "../../util/TypeUtil";
import { Intersection } from "../Intersection";
import { Circle } from "../math/Circle";
import { Matrix } from "../math/Matrix";
import { BaseShape, ShapeType } from "./BaseShape";
import { BoxShape } from "./BoxShape";
import { CircleShape } from "./CircleShape";
import { PolygonShape } from "./PolygonShape";

/**
 * 镂空圆形图形
 * (适合用来做技能范围判定，不能用来做常规碰撞检测)
 */
export default class HollowCircleShape extends BaseShape {

    /** 外圆 */
    readonly worldCircle = new Circle();
    /** 内圆 */
    readonly worldCircleIn = new Circle();

    /** 外圆半径 */
    radius: number = 0;
    /** 内圆半径 */
    radiusIn: number = 0;

    /**
     * 设置半径
     * @param radius
     * @param radiusIn
     */
    setRaidus(radius: number, radiusIn: number) {
        this.radius = radius;
        this.radiusIn = radiusIn;
        return this;
    }

    getType(): ShapeType {
        return ShapeType.hollowCircle;
    }

    update(pos: Readonly<IVec2>, trans?: Readonly<Matrix>): this {
        this.worldCircle.setPosTo(this);
        this.worldCircleIn.setPosTo(this);

        if (trans) {
            trans.transformPointN(this.worldCircle);
            trans.transformPointN(this.worldCircleIn);
            const scale = Math.max(trans.getScaleX(), trans.getScaleY());
            this.worldCircle.radius = this.radius * scale;
            this.worldCircleIn.radius = this.radiusIn * scale;
        } else {
            this.worldCircle.radius = this.radius;
            this.worldCircleIn.radius = this.radiusIn;
        }

        this.worldCircle.addPosTo(pos);
        this.worldCircleIn.addPosTo(pos);

        const d = this.worldCircle.radius * 2;
        this.worldAABB.setRect(
            this.worldCircle.x - this.worldCircle.radius,
            this.worldCircle.y - this.worldCircle.radius,
            d, d
        );

        return this;
    }

    testCollide(shape: Readonly<BaseShape>): boolean {
        switch (shape.getType()) {
            case ShapeType.circle:
                const circle = (shape as CircleShape).worldCircle;
                return Intersection.circleCircle2(this.worldCircle, circle)
                    && !Intersection.circleInCircle(circle, this.worldCircleIn);
            case ShapeType.rect:
                return Intersection.rectCircle2(shape.worldAABB, this.worldCircle)
                    && !Intersection.rectInCircle(shape.worldAABB, this.worldCircleIn);
            case ShapeType.box:
            case ShapeType.polygon:
                const polygon = (shape as BoxShape | PolygonShape).worldPolygon;
                return Intersection.rectRect(this.worldAABB, shape.worldAABB)
                    && Intersection.polygonCircle2(polygon, this.worldCircle)
                    && !Intersection.polygonInCircle(polygon, this.worldCircleIn);
        }

        throw new Error(`未实现碰撞方法：${TypeUtil.getCls(this).name} -> ${TypeUtil.getCls(shape).name}`);
    }

}